home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / UTILITIE / LHX.ZIP / LHX.C < prev    next >
C/C++ Source or Header  |  1989-04-15  |  6KB  |  318 lines

  1. /* LHX.C -- An LHARC archive tester/scanner
  2.  *
  3.  * version 1.0 by Mark Armbrust, 15 April 1985   (IRS? Just say NO!)
  4.  *
  5.  * The code in this module is public domain -- do whatever you want with it */
  6.  
  7. static char version[] = "@(#)lhx.c version 1.0 by Mark Armbrust";
  8.  
  9. #include <process.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <stdlib.h>
  14. #include <malloc.h>
  15.  
  16. #define MAIN
  17. #include "lhx.h"
  18.  
  19. /* private routines */
  20.  
  21. PRIVATE void    Usage        (void);
  22. PRIVATE int     Match        (char *, char *);
  23. PRIVATE int     WC_Match    (char *, char *);
  24.  
  25.  
  26.  
  27. PUBLIC void        main    (argc, argv)
  28.  
  29. int                  argc;
  30. char            *    argv[];
  31. {
  32. char            *    arcname,
  33.                 *    arcpath;
  34. FILE            *    arcfile;
  35. struct fname    *    filename,
  36.                 *    filenames;
  37. char            *    p,
  38.                 *    q;
  39. struct find_t        findbuf;
  40. int                    i;
  41. int                    exitcode;
  42.  
  43.  
  44. if (argc < 2)
  45.     Usage();
  46.  
  47. --argc;
  48. ++argv;
  49.  
  50. mode = LIST;                    /* set default mode */
  51.  
  52. if (**argv == '-') {            /* get mode switch if present */
  53.     switch (*++*argv) {
  54.  
  55.         case 'e':
  56.         case 'E':
  57.             mode = EXTRACT;
  58.             break;
  59.  
  60.         case 'l':
  61.         case 'L':
  62.             mode = LIST;
  63.             break;
  64.  
  65.         case 's':
  66.         case 'S':
  67.             mode = SCAN;
  68.             break;
  69.  
  70.         case 't':
  71.         case 'T':
  72.             mode = TEST;
  73.             break;
  74.  
  75.         default:
  76.             Usage();
  77.  
  78.         }
  79.     --argc;
  80.     ++argv;
  81.     }
  82.  
  83. header_start = -1;                /* disable starting offset options */
  84. file_start = -1;
  85. file_size = -1;
  86. file_type = -1;
  87. file_name[0] = 0;
  88.  
  89. if (argc && **argv == '@') {    /* get starting offsets */
  90.     if (mode & SCAN)
  91.         fprintf (stderr, "lhx:  WARNING -- offsets ignored.\n");
  92.     else {
  93.         mode |= AT;
  94.         i = sscanf (++*argv, "%ld,%ld,%ld,%d,%s", &header_start, &file_start, 
  95.                     &file_size, &file_type, file_name);
  96.         if (!i)
  97.             Usage();
  98.         }
  99.     --argc;
  100.     ++argv;
  101.     }
  102.  
  103. if (argc) {                        /* get archive name */
  104.     arcname = *argv;
  105.     --argc;
  106.     ++argv;
  107.     }
  108. else
  109.     Usage();
  110.  
  111. if (argc == 0) {                /* get file names if present */
  112.     filenames = malloc (sizeof (struct fname));
  113.     filenames->name = "*.*";
  114.     filenames->next = 0;        /* none specified, assume *.* */
  115.     }
  116. else {
  117.     if (mode & SCAN)
  118.         fprintf (stderr, "lhx:  WARNING -- filenames ignored.\n");
  119.     else {
  120.         filenames = 0;                /* use the rest of the names to build a */
  121.         while (argc--) {            /* linked list of filenames to match.    */
  122.             filename = malloc (sizeof (struct fname));
  123.             filename->name = *argv++;
  124.             filename->next = filenames;
  125.             filenames = filename;
  126.             }
  127.         }
  128.     }
  129.  
  130. if (strpbrk (arcname, "\\/:")) {
  131.     arcpath = strdup(arcname);        /* strip path from arcname */
  132.     p = arcpath - 1;
  133.     while (q = strpbrk (++p, "\\/:"))
  134.         p = q;
  135.     *p = '\0';
  136.     }
  137. else
  138.     arcpath = "";
  139.  
  140. strcpy (name, arcname);
  141.  
  142. p = name;
  143. if (q = strrchr (p, '\\')) 
  144.     p = q + 1;
  145. if (q = strrchr (p, '/')) 
  146.     p = q + 1;
  147. if ( ! strchr (p, '.'))
  148.     strcat (name, ".lzh");
  149.  
  150. if (_dos_findfirst (name, _A_NORMAL | _A_RDONLY ,&findbuf)) {
  151.     fprintf (stderr, "lhx:  ERROR -- could not find any archive files "
  152.             "matching '%s'.\n", arcname);
  153.     exit (-1);
  154.     }
  155.  
  156. exitcode = 0;
  157.  
  158. do {
  159.     strcpy (name, arcpath);
  160.     strcat (name, findbuf.name);
  161.     arcfile = fopen (name, "rb");
  162.     if ( ! arcfile) {
  163.         fprintf (stderr, "lzx:  ERROR -- could not open archive file '%s'.\n",
  164.                 name);
  165.         exit (-1);
  166.         }
  167.  
  168.     switch (mode & MODES) {
  169.  
  170.         case EXTRACT:
  171.         case LIST:
  172.         case TEST:
  173.             exitcode += Process (arcfile, filenames);
  174.             break;
  175.  
  176.         case SCAN:
  177.             Scan (arcfile);
  178.             break;
  179.         }
  180.  
  181.     fclose (arcfile);
  182.     } while ( !(mode & AT) && ! _dos_findnext (&findbuf) );
  183.  
  184. exit (exitcode);
  185. }
  186.  
  187.  
  188.  
  189. PRIVATE void    Usage    ()
  190.  
  191. {
  192. printf ("\n");
  193. printf ("usage: lhx [-elst] [@hdr,data,size,type,name] arcname [filename ...]\n\n");
  194. printf ("           E => extract files\n");
  195. printf (" (default) L => list archive contents\n");
  196. printf ("           S => scan damaged archive\n");
  197. printf ("           T => test archive\n\n");
  198. printf ("           @hdr,data,size,type,name => where to start in a damaged archive.\n");
  199. exit (1);
  200. }
  201.  
  202.  
  203.  
  204. PUBLIC int        MatchAny (name, filenames)
  205.  
  206. char            *    name;
  207. struct fname    *    filenames;
  208. {
  209.  
  210. do {
  211.     if (Match (name, filenames->name))
  212.         return 1;
  213.     filenames = filenames->next;
  214.     }
  215. while (filenames);
  216.  
  217. return 0;
  218. }
  219.  
  220.  
  221.  
  222. PRIVATE int     Match (file, pattern)
  223.  
  224.     char            *file;
  225.     char            *pattern;
  226.     {
  227.     int                i;
  228.     register char    *filename;
  229.     register char    *s;
  230.  
  231.  
  232. /* strip off the leading path and trailing modifiers (zoo ver. number, etc.) */
  233.  
  234.     filename = file;
  235.     if (s = strrchr (filename, '/')) filename = s+1;
  236.     if (s = strrchr (filename, '\\')) filename = s+1;
  237.     filename = strdup (filename);
  238. /*    if (!filename) Abort ("filename strdup failed in Match"); */
  239.     if (s = strpbrk (filename, ";*, ")) *s = '\0';
  240.  
  241.     i = WC_Match (filename, pattern);
  242.     free (filename);
  243.  
  244.     return i;
  245.     }
  246.  
  247.  
  248.  
  249. /*    Returns TRUE if s1 and s2 match under modified MSDOS wildcard rules.
  250.  *
  251.  *    Two strings match if all their substrings between : . / and \ match
  252.  *    using * and ? as wildcards in the substrings.
  253.  *
  254.  *    Note that MSDOS is a bit schitzo about matching strings that end in : and .
  255.  *    This code will only match them 1-to-1.  For example 'DIR X' matches X.* or
  256.  *    X\*.* depending on what X is.  We do, however, match 'X' to 'X.' and 'X.*'
  257.  *
  258.  */
  259.  
  260. PRIVATE int     WC_Match (s1, s2)
  261.  
  262.     register    char    *s1;
  263.     register    char    *s2;
  264.     {
  265.  
  266. #define IS_SLANT(c)        ((c) == '/' || (c) == '\\')
  267. #define IS_FILE_SEP(c)    ( (c) == ':' || (c) == '.' || IS_SLANT(c) )
  268.  
  269.     while (1) {
  270.  
  271.         if (*s1 == '*' || *s2 == '*') {
  272.             while (*s1 && ! IS_FILE_SEP (*s1))
  273.                 ++s1;
  274.             while (*s2 && ! IS_FILE_SEP (*s2))
  275.                 ++s2;
  276.             continue;
  277.             }
  278.  
  279.         if (*s1 == '?') {
  280.             if (!*s2 || IS_FILE_SEP (*s2))
  281.                 return 0;
  282.             ++s1;
  283.             ++s2;
  284.             continue;
  285.             }
  286.  
  287.         if (*s2 == '?') {
  288.             if (!*s1 || IS_FILE_SEP (*s1))
  289.                 return 0;
  290.             ++s1;
  291.             ++s2;
  292.             continue;
  293.             }
  294.  
  295.         if (*s1 == 0 && *s2 == '.') {
  296.             ++s2;
  297.             continue;
  298.             }
  299.  
  300.         if (*s2 == 0 && *s1 == '.') {
  301.             ++s1;
  302.             continue;
  303.             }
  304.  
  305.         if (toupper(*s1) != toupper(*s2))
  306.             return 0;
  307.  
  308.         if (*s1 == 0)        /* then (*s2 == 0) as well! */
  309.             break;
  310.  
  311.         ++s1;
  312.         ++s2;
  313.         }
  314.  
  315.     return 1;
  316.     }
  317.  
  318.